#include "fastbuffermanager.h"
#include "fastbufferhandler.h"
#include <QThread>
#include <Qtdebug>
#include <QApplication>
#include <QDir>

FastBufferManager::FastBufferManager()
{
}

void FastBufferManager::createFastBufferList(int bufferSize, int bufferCount)
{
    if (bufferCount > sizeof(m_bufferOccupyFlag) * 8)
    {
        bufferCount = sizeof(m_bufferOccupyFlag) * 8;
    }
    m_bufferReadyMask = (1 << bufferCount) - 1;
    m_bufferOccupyFlag = 0;
    m_bufferIsReady = false;
    m_bufferReadyFlag = 0;

    m_sendMap.resize(bufferCount);
    m_bufferList.clear();
    for (int i = 0; i < bufferCount; i++)
    {
        m_sendMap[i] = i; // 初始化默认映射关系
        QVector<double> buffer;
        buffer.resize(bufferSize);
        m_bufferList.push_back(buffer);

        m_bufferHandlerList << new FastBufferHandler(i, this);
    }
}

QVector<double> &FastBufferManager::fastBuffer(int id)
{
    if (m_bufferIsReady) // 缓存区就绪的时候根据映射关系返回缓存区
    {
        id = m_sendMap[id];
    }

    if (id < 0 || id >= m_bufferList.size())
    {
        return m_bufferList[0];
    }
    return m_bufferList[id];
}

void FastBufferManager::waitBufferReady(unsigned long waitMask)
{
    while (m_bufferIsReady != waitMask)
    {
        // qDebug()<<"waitBufferReady"<<m_bufferIsReady<<waitMask;
        // QThread::msleep(0);
    }
    // qDebug()<<"waitBufferReady success"<<m_bufferOccupyFlag<<waitMask;
}

void FastBufferManager::readyToRead(int id)
{
    id = m_sendMap[id];
    while (!(m_bufferOccupyFlag & (1 << id)))
    {
        // qDebug()<<"readyToRead"<<id<<m_bufferOccupyFlag;
        // QThread::usleep(0);
    }
}

void FastBufferManager::readyToWrite(int id)
{
    while (m_bufferOccupyFlag & (1 << id))
    {
        // QThread::msleep(0);
    }
}

FastBufferHandler *FastBufferManager::bufferHandler(int id)
{
    if (id < 0 || id >= m_bufferHandlerList.size())
    {
        return nullptr;
    }

    return m_bufferHandlerList.at(id);
}

bool FastBufferManager::connect(int senderId, int receiverId)
{
    if (receiverId < 0 || receiverId >= m_sendMap.size())
    {
        return false;
    }
    if (senderId < 0 || senderId >= m_sendMap.size())
    {
        return false;
    }
    m_sendMap[receiverId] = senderId;
    return true;
}

void FastBufferManager::markBuffer(int id, bool isMarked)
{
    if (id < 0 || id >= m_bufferList.size())
    {
        return;
    }
    if (isMarked)
    {
        m_bufferOccupyFlag |= (1 << id);
    }
    else
    {
        m_bufferOccupyFlag &= ~(1 << id);
    }
}

void FastBufferManager::markBufferReady(int id, bool isReady)
{
    if (id < 0 || id >= m_bufferList.size())
    {
        return;
    }
    if (isReady)
    {
        m_bufferReadyFlag |= (1 << id);
        if (m_bufferReadyFlag == m_bufferReadyMask)
        {
            m_bufferIsReady = 1;
        }
    }
    else
    {
        m_bufferReadyFlag &= ~(1 << id);
        if (m_bufferReadyFlag == 0)
        {
            m_bufferIsReady = 0;
        }
    }
}

void FastBufferManager::setTimeout(int timeoutValue)
{
    m_timeoutValue = timeoutValue;
}

void FastBufferManager::recordTimeout(long long ns)
{
    if (m_timeoutValue <= 0)
    {
        return;
    }
    m_timeoutCount += ns > m_timeoutValue;
}

void FastBufferManager::printTimeCountLog()
{
    // 将CSV字符串写入文件
    QString csvFilePath = qApp->applicationDirPath() + QString("/log/timecount.csv");
    QDir dir(qApp->applicationDirPath());
    if (!dir.exists("log"))
    {
        dir.mkdir("log");
    }
    QFile outputFile(csvFilePath);
    if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        qDebug() << "Failed to open the output file: " << outputFile.errorString();
    }
    QTextStream out(&outputFile);
    QString csvString;

    // 输出列标题
    csvString += "handler_id";
    for (size_t i = 0; i < m_bufferHandlerList.count(); ++i)
    {
        csvString += "," + QString("thread[%1]").arg(m_bufferHandlerList.at(i)->id());
    }
    csvString += "\n";
    out << csvString;

    for (int i = 0;; i++)
    {
        QString lineStr = QString("LOOP[%1]").arg(i);
        for (const auto &handler : m_bufferHandlerList)
        {
            const QVector<long long> &timeCount = handler->timeCountRecord();
            lineStr += "," + QString::number(timeCount[i]);
        }
        lineStr += "\n";
        out << lineStr;

        // qDebug() << i << m_bufferHandlerList.first()->timeCountRecord().size();
        if (i >= (m_bufferHandlerList.first()->timeCountRecord().size() - 1))
        {
            break;
        }
    }
    outputFile.close();
}
